package com.zsrt.scott;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.zsrt.scott.ano.Autowired;

public class ZSRTClassPathXmlApplicationContext {
	
	
	private List<File> fileList = new ArrayList<File>();
	
	
	
	private Map<String, Object> ioc = new HashMap<String, Object>();
	
	
	public ZSRTClassPathXmlApplicationContext(){}
	
	
	public void dgFile(File file){
		
		boolean flag = file.isDirectory();
		System.out.println(flag);
		if(flag == true){
			//说明是1个文件夹
			File[] fs = file.listFiles();
			System.out.println(fs.length);
			for(File f:fs){
				dgFile(f);
			}
		}else{
			fileList.add(file);
		}
		
	}
	
	
	
	
	public ZSRTClassPathXmlApplicationContext(String path){
		
		
		//解析xml
		
		try {
			//1 根据传过来的路径  使用dom4j解析xml
			SAXReader reader = new SAXReader();  
			//读取文件 转换成Document  
			Document document = reader.read(new File("src/main/resources/"+path));
			
			System.out.println(document.getClass().getName());
			
			//拿到根节点 beans
			Element root = document.getRootElement();
			
			
			Element scan = root.element("component-scan");
			
			System.out.println(scan.attributeValue("base-package"));
			
			
			String basePackage= scan.attributeValue("base-package");
			
			
			//扫描basePackage包及其子包  扫描有 @Servive @Controller @Component 类  让它加入spring ioc容器
			
			
			
			
			// 直接找  com.zsrt.scott 找到  @Service注解的类   StudentServiceImpl  ?
			
			
			
			//io
			
			File file = new File("src/main/java/com/zsrt/scott");
			
			
			
			dgFile(file);
			
			System.out.println(fileList.size());
			
			//那个 .java文件上有@Service注解
			
			System.out.println("------------------------------------------------------------------");
			for(File f:fileList){
				
				//com.zsrt.scott.service.StudentServiceImpl
				String full  = f.getPath();
				
				//System.out.println(full);
				//src\main\java\com\zsrt\scott\service\StudentServiceImpl.javaStudentServiceImpl.java
				
				full  = full.replaceAll("\\\\", ".");
				
				
				full= full.substring(14);
				full =full.substring(0, full.length()-5);
				
				
				//字符串类型的  类的对象
				
				Class clazz = Class.forName(full);
				
				
				//把注解排除掉
				
				boolean flag01 = clazz.isAnnotation();
				
				
				boolean flag02 = clazz.isInterface();
				
				if(flag01 == false  && flag02 == false){
					
					//这个.java文件既不是接口 也不是注解   newInstance调用的是无参的构造方法
					
					
					
					//用反射生成字符串 对应的类的对象    然后用发射看这个类上是否由@Service注解   如果由注解 必须要生成这个类的对象 key=类名首字母小写  value 类的对象
					
					
					Annotation[] as = clazz.getAnnotations();
					
					//System.out.println("as.length="+as.length);
					
					//生成所有的dao
					generateDao(clazz, as);
					
					
					//生成所有的service 并且把dao注入到service中
					generateService(clazz, as);
					
					
					//2 把dao注入service?
					
				}
				
				
			}
			
			
			
			
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}


	private void generateDao(Class clazz, Annotation[] as) throws InstantiationException, IllegalAccessException {
		//利用反射生成需要new出来对象开始...
		if(as !=null && as.length>=1){
			for(Annotation a:as){
				//System.err.println("====");
				//System.err.println(a);
				String parserAnntation = a.toString();
				//System.out.println(parserAnntation);
				
				//com.zsrt.scott.ano.Service  @com.zsrt.scott.ano.Service(value=)
				//注解怎么比较呢?
				
				if(parserAnntation.contains("com.zsrt.scott.ano.Component") ){
					
					//System.out.println("要生成"+object+"的对象...");
					
					
					Object object = clazz.newInstance();
					
					
					String quan = object.getClass().getName();
					
					int begin = quan.lastIndexOf(".");
					
					String id = quan.substring(begin+1);
					
					id= id.substring(0,1).toLowerCase()+id.substring(1);
					System.out.println(id);
					ioc.put(id, object);
				}
			}
		}
		//利用反射生成需要new出来对象开始...
	}
	private void generateService(Class clazz, Annotation[] as) throws InstantiationException, IllegalAccessException {
		//利用反射生成需要new出来对象开始...
		if(as !=null && as.length>=1){
			for(Annotation a:as){
				//System.err.println("====");
				//System.err.println(a);
				String parserAnntation = a.toString();
				//System.out.println(parserAnntation);
				
				//com.zsrt.scott.ano.Service  @com.zsrt.scott.ano.Service(value=)
				//注解怎么比较呢?
				
				if(parserAnntation.contains("com.zsrt.scott.ano.Service") ){
					
					//System.out.println("要生成"+object+"的对象...");
					
					
					Object object = clazz.newInstance();
					
					
					String quan = object.getClass().getName();
					
					int begin = quan.lastIndexOf(".");
					
					String id = quan.substring(begin+1);
					
					id= id.substring(0,1).toLowerCase()+id.substring(1);
					System.out.println(id);
					
					
					//如果service中有属性 而且加了com.zsrt.scott.ano.Autowired 注解
					
					//1 拿到所有的属性 来比较
					
					Field[] fs = clazz.getDeclaredFields();
					
					for(Field f:fs){
						Autowired aw = f.getAnnotation(Autowired.class);
						Resource  rs = f.getAnnotation(Resource.class);
						
						if(aw != null || rs != null){
							
							//1 知道属性类型  然后 通过类型去ioc容器中去取
							
							Class  ft = f.getType();
							
							System.out.println("ft="+ft.getName());
							
							
							Set<String> ks = ioc.keySet();
							
							Iterator<String> it = ks.iterator();
							
							while(it.hasNext()){
								String key = it.next();
								
								Object duixiang = ioc.get(key);
								
								if(duixiang.getClass().getName().equals(ft.getName())){
									f.setAccessible(true);
									
									f.set(object, duixiang);
								}
							}
							
						}
						
					}
					
					
					
					
					//能不直接加?
					ioc.put(id, object);
				}
			}
		}
		//利用反射生成需要new出来对象开始...
	}
	
	
	public Object getBean(String id){
		return ioc.get(id);
	}

}
